package com.lei.app.controller.socket.web;

import com.lei.app.dto.SocketSendDto;
import com.lei.app.utils.enums.SocketStateEnum;
import com.lei.app.websocket.NutIocWebSocketConfigurator;
import lombok.extern.slf4j.Slf4j;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.nutz.lang.Strings;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/***
 *   推送消息通道
 * @author zxq(956607644@qq.com)
 * @date 2020/4/9 9:45

 * @return
 */
@ServerEndpoint(value = "/", configurator = NutIocWebSocketConfigurator.class)
@IocBean
@Slf4j
public class WebSockets {

    /**
     * 全局缓存，用于存储已存在的socket客户端连接
     */
    private static ConcurrentMap<String, Session> existSocketClientMap = new ConcurrentHashMap<String, Session>(50);

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        doClose(session,closeReason);
        removeUser(session);
    }


    @OnError
    public void onError(Session session, Throwable thr) {
        doError(session, thr);
        removeUser(session);
    }


    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        doOpen(session, endpointConfig);
    }


    private void doClose(Session session, CloseReason closeReason) {
        // 删除数据
    }

    private void doError(Session session, Throwable thr) {
        // 删除数据
    }

    private void removeUser(Session session) {
        try {
            if (session.isOpen()) {
                session.close();
            }
            existSocketClientMap.remove(session.getId());
        }catch (Exception e){

        }
    }

    private void doOpen(Session session, EndpointConfig config) {
        session.addMessageHandler(new MyMessageHandle(session));
        existSocketClientMap.put(session.getId(), session);
        try {
            autoSendMessage("<span style='color:red;'>你好，欢迎使用该工具</span>", session.getId());
        }catch (Exception e){
            log.error("",e);
        }
    }

    /***
     *  接收消息
     * @author zxq(956607644@qq.com)
     * @date 2020/4/9 11:40
     * @param message
     * @param session
     * @return void
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            doMessage(message, session);
        }catch (Exception e){
            log.debug("发送消息失败：message = " + message, e);
            onError(session,e);
        }
    }

    private void doMessage(String message, Session session) throws Exception {
        if(Strings.isBlank(message)){
            onError(session,new RuntimeException("消息类型错误"));
            return;
        }
        String msg = "";
        SocketSendDto send = Json.fromJson(SocketSendDto.class, message);
        if(SocketStateEnum.SEND.getValue().equals(send.getFunctionCode())){
            msg = send.getMessage();
            SocketSendDto request =
                    SocketSendDto.builder()
                    .functionCode(SocketStateEnum.RESPONSE.getValue())
                    .message(msg)
                    .build();
            session.getAsyncRemote().sendText(Json.toJson(request));
        }

    }


    /***
     *   发送消息
     * @author zxq(956607644@qq.com)
     * @date 2020/4/9 11:35
     * @param message
     * @param sessionId
     * @return void
     */
    public void autoSendMessage(String message, String sessionId) throws Exception {
        Session session = existSocketClientMap.get(sessionId);
        if (session != null && session.isOpen()) {
            String data = Json.toJson(
                    SocketSendDto.builder()
                    .functionCode(SocketStateEnum.AUTO.getValue())
                    .message(message)
                    .build(), JsonFormat.full());
            session.getAsyncRemote().sendText(data);
        }
    }



    public class MyMessageHandle implements MessageHandler.Whole<String> {

        private Session session;

        public MyMessageHandle(Session session) {
            this.session = session;
        }

        @Override
        public void onMessage(String message) {
            WebSockets.this.onMessage(message, session);
        }
    }
}